package com.cetcs.kmga.dataManager.util;

import com.cetcs.kmga.dataManager.entity.logManager.vo.KeyValueOut;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

import javax.servlet.ServletOutputStream;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by yyangs on 2017/4/12.
 */
public class ExcelExportUtil {

    public static void main(String[] args) {
        List<KeyValueOut> lalala = Lists.newArrayList( );
        KeyValueOut keyValueOut1 = new KeyValueOut( );
        keyValueOut1.setName("zyy");
        keyValueOut1.setValue("456");
        lalala.add(keyValueOut1);
        KeyValueOut keyValueOut2 = new KeyValueOut( );
        keyValueOut2.setName("liyuan");
        keyValueOut2.setValue("455556234243242343242342");
        lalala.add(keyValueOut2);
        //excel 文件名
        String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date( )) + "workbook.xls";
        //excel 表格头
        Map<String, String> map = new HashMap<>( );
        map.put("name", "姓名");
        map.put("value", "值");
        ExcelExportUtil.createWorkBook(lalala, fileName, map);
    }

    /**
     * @param lists    需要导出的数据
     * @param fileName 创建excel的文件名
     * @param map      创建excel的表格头
     * @throws Exception
     */
    //使用POI创建excel工作簿
    public static <T> byte[] createWorkBook(List<T> lists, String fileName, Map<String, String> map) {


        byte[] content = null;
        try {
            //通过反射获取所有的字段
            T object = lists.get(0);
            Field[] field = object.getClass( ).getDeclaredFields( );
            //创建excel工作簿
            Workbook wb = new HSSFWorkbook( );
            // 创建单元格样式
            HSSFCellStyle headHSSFCellStyle = getHeadHSSFCellStyle(wb);
            HSSFCellStyle bodyHSSFCellStyle = getBodyHSSFCellStyle(wb);
            //创建第一个sheet（页），命名为 new sheet
            Sheet sheet = wb.createSheet("sheet1");
            //Row 行
            //Cell 方格
            // Row 和 Cell 都是从0开始计数的
            int rowNum = 0;
            int cellNum = 0;
            // 创建一行，在页sheet上
            Row row = sheet.createRow((short) rowNum++);
            cellNum = 0;
            /**
             * 每创建一行 cellNum都需要置0
             */
            // 创建第一个行 头
            Cell cell = row.createCell(cellNum++);
            cell.setCellStyle(headHSSFCellStyle);
            //设置方格的显示
            cell.setCellValue("序号");
            for (int i = 0; i < field.length; i++) {
                cell = row.createCell(cellNum++);
                cell.setCellStyle(headHSSFCellStyle);
                //设置方格的显示
                cell.setCellValue(map.get(field[i].getName( )));
            }
            //数据显示
            for (int i = 0; i < lists.size( ); i++) {
                row = sheet.createRow((short) rowNum++);
                cellNum = 0;
                cell = row.createCell(cellNum++);
                cell.setCellStyle(bodyHSSFCellStyle);
                cell.setCellValue(i + 1);
                //创建每一个单元格
                for (int j = 0; j < field.length; j++) {
                    cell = row.createCell(cellNum++);
                    //设置方格的显示
                    Method m = object.getClass( ).getMethod("get" + field[j].getName( ).substring(0, 1).toUpperCase( ) + field[j].getName( ).substring(1));
                    cell.setCellStyle(bodyHSSFCellStyle);
                    //判断字段类型
                    if (field[j].getGenericType( ).toString( ).equals("class java.lang.String")) {
                        //如果该字段是String类型
                        cell.setCellValue((String) m.invoke(lists.get(i)));
                    } else if (field[j].getGenericType( ).toString( ).equals("class java.lang.Integer")) {
                        //如果是integer类型
                        cell.setCellValue((Integer) m.invoke(lists.get(i)));
                    } else {
                        continue;
                    }
                }
            }
            for (int i = 0; i <= lists.size( ); i++) {
                sheet.autoSizeColumn((short) i); //调整列宽度
            }
            ByteArrayOutputStream os = new ByteArrayOutputStream( );


            // 把上面创建的工作簿输出到文件中
            wb.write(os);

            content = os.toByteArray( );
            //is = new ByteArrayInputStream(content);
            os.close( );

        } catch (Exception e) {
            e.printStackTrace( );
            System.out.println("创建失败");
        }

        return content;
    }


    /**
     * 将数据导出成Excel,Excel版本是2007以上斑斑
     *
     * @param title    excel名称
     * @param headers  表头
     * @param dataList 需要导成Excel的数据
     */
    public static void exportXlxsExcel(String title, List<String> headers, List<List<String>> dataList, ServletOutputStream os) throws IOException {

        XSSFWorkbook workbook = new XSSFWorkbook( );                     // 创建工作簿对象
        XSSFSheet sheet = workbook.createSheet(title);                  // 创建工作表


        //sheet样式定义【getColumnTopStyle()/getStyle()均为自定义方法 - 在下面  - 可扩展】
        XSSFCellStyle columnTopStyle = getHeadXSSFCellStyle(workbook);//获取列头样式对象
        XSSFCellStyle style = getBodyXSSFCellStyle(workbook);                  //单元格样式对象

        XSSFCellStyle speicalSyle = workbook.createCellStyle( );
        speicalSyle.setWrapText(true);
        // 定义所需列数
        int columnNum = headers.size( );
        XSSFRow rowRowName = sheet.createRow(0);                // 在索引2的位置创建行(最顶端的行开始的第二行)

        // 将列头设置到sheet的单元格中
        for (int n = 0; n < columnNum; n++) {
            //创建列头对应个数的单元格
            XSSFCell cellRowName = rowRowName.createCell(n);
            //设置列头单元格的数据类型
            cellRowName.setCellType(HSSFCell.CELL_TYPE_STRING);
            XSSFRichTextString text = new XSSFRichTextString(headers.get(n));
            //设置列头单元格的值
            cellRowName.setCellValue(text);
            //设置列头单元格样式
            cellRowName.setCellStyle(columnTopStyle);
        }

        //将查询出的数据设置到sheet对应的单元格中
        for (int i = 0; i < dataList.size( ); i++) {

            List<String> columnValArr = dataList.get(i);//遍历每个对象
            XSSFRow row = sheet.createRow(i + 1);//创建所需的行数
            short hi = 30;
            row.setHeightInPoints(hi);
            for (int j = 0; j < columnValArr.size(); j++) {
                XSSFCell cell = row.createCell(j, XSSFCell.CELL_TYPE_STRING);  //设置单元格的数据类型
                if (!StringUtils.isNotBlank(columnValArr.get(j))) {
                    cell.setCellValue("");
                    cell.setCellStyle(style);
                } else {
                    cell.setCellValue(columnValArr.get(j));
                    cell.setCellStyle(style);
                }
            }
        }
        //让列宽随着导出的列长自动适应
        for (int colNum = 0; colNum < columnNum; colNum++) {
            int columnWidth = sheet.getColumnWidth(colNum) / 256;
            for (int rowNum = 0; rowNum < sheet.getLastRowNum( ); rowNum++) {
                XSSFRow currentRow;
                //当前行未被使用过
                if (sheet.getRow(rowNum) == null) {
                    currentRow = sheet.createRow(rowNum);
                } else {
                    currentRow = sheet.getRow(rowNum);
                }
                if (currentRow.getCell(colNum) != null) {
                    XSSFCell currentCell = currentRow.getCell(colNum);
                    if (currentCell.getCellType( ) == HSSFCell.CELL_TYPE_STRING) {
                        int length = currentCell.getStringCellValue( ).getBytes( ).length;
                        if (columnWidth < length) {
                            columnWidth = length;
                        }
                    }
                }
            }
            if ((columnWidth + 4) < 255) {
                sheet.setColumnWidth(colNum, (columnWidth + 4) * 256);
            } else {
                sheet.setColumnWidth(colNum, 40 * 256);
            }
        }
        workbook.write(os);
    }

    /**
     * @param mapList  需要导出的数据
     * @param fileName 文件名称
     * @param headMap  导出Ex
     * @return
     */
    //使用POI创建excel工作簿
    public static void createWorkBookForMap(List<Map<String, String>> mapList, String fileName, Map<String, String> headMap, ServletOutputStream os) throws Exception {
        try {
            //创建excel工作簿
            Workbook wb = new HSSFWorkbook( );
            // 创建单元格样式
            HSSFCellStyle headHSSFCellStyle = getHeadHSSFCellStyle(wb);
            HSSFCellStyle bodyHSSFCellStyle = getBodyHSSFCellStyle(wb);
            //创建第一个sheet（页），命名为 new sheet
            Sheet sheet = wb.createSheet("sheet1");
            //Row 行
            //Cell 方格
            // Row 和 Cell 都是从0开始计数的
            int rowNum = 0;
            int cellNum = 0;
            // 创建一行，在页sheet上
            Row row = sheet.createRow((short) rowNum++);
            cellNum = 0;
            /**
             * 每创建一行 cellNum都需要置0
             */
            // 创建第一个行 头
            Cell cell = row.createCell(cellNum++);
            cell.setCellStyle(headHSSFCellStyle);
            //设置方格的显示
            cell.setCellValue("序号");
            for (Map.Entry<String, String> entry : headMap.entrySet( )) {
                cell = row.createCell(cellNum++);
                cell.setCellStyle(headHSSFCellStyle);
                //设置方格的显示
                cell.setCellValue(entry.getValue( ));

            }
            //数据显示
            for (int i = 0; i < mapList.size( ); i++) {
                row = sheet.createRow((short) rowNum++);
                cellNum = 0;
                cell = row.createCell(cellNum++);
                cell.setCellStyle(bodyHSSFCellStyle);
                cell.setCellValue(i + 1);
                //创建每一个单元格
                for (Map.Entry<String, String> entry : headMap.entrySet( )) {
                    cell = row.createCell(cellNum++);
                    //设置方格的显示
                    cell.setCellStyle(bodyHSSFCellStyle);
                    //判断字段类型
                    cell.setCellValue(mapList.get(i).get(entry.getKey( )));
                }
            }
            for (int i = 0; i <= mapList.size( ); i++) {
                sheet.autoSizeColumn((short) i); //调整列宽度
            }
//                // fixme 保存的目录
//                String path = "E://";
//                //判断文件夹是否存在
//                File directory = new File(path);
//                if (!directory.exists() && !directory.isDirectory()) {
//                    directory.mkdir();
//                }
//                //创建一个文件 命名为workbook.xls
//                FileOutputStream fileOut = new FileOutputStream(path + "/" + fileName);


            // 把上面创建的工作簿输出到文件中
            wb.write(os);

            //is = new ByteArrayInputStream(content);
            //os.close();

        } catch (Exception e) {
            e.printStackTrace( );
            throw new Exception(e.getMessage( ));
        }
    }


    /**
     * 获得标题的样式
     *
     * @param wb
     * @return
     */
    public static HSSFCellStyle getHeadHSSFCellStyle(Workbook wb) {
        // 创建单元格样式
        HSSFCellStyle cellStyle = (HSSFCellStyle) wb.createCellStyle( );
        // 指定单元格居中对齐
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 指定单元格垂直居中对齐
        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        // 指定当单元格内容显示不下时自动换行
        cellStyle.setWrapText(true);
        // 设置单元格字体
        HSSFFont font = (HSSFFont) wb.createFont( );
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 14);
        cellStyle.setFont(font);
        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 下边框
        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);// 左边框
        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);// 上边框
        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);// 右边框
        return cellStyle;
    }


    /**
     * 获得标题的样式
     *
     * @param wb
     * @return
     */
    public static XSSFCellStyle getHeadXSSFCellStyle(Workbook wb) {
        // 创建单元格样式
        XSSFCellStyle cellStyle = (XSSFCellStyle) wb.createCellStyle( );
        // 指定单元格居中对齐
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 指定单元格垂直居中对齐
        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        // 指定当单元格内容显示不下时自动换行
        cellStyle.setWrapText(true);
        // 设置单元格字体
        XSSFFont font = (XSSFFont) wb.createFont( );
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 14);
        cellStyle.setFont(font);
        cellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN); // 下边框
        cellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);// 左边框
        cellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);// 上边框
        cellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN);// 右边框
        return cellStyle;
    }

    /**
     * 获得标题的样式
     *
     * @param wb
     * @return
     */
    public static HSSFCellStyle getBodyHSSFCellStyle(Workbook wb) {
        // 创建单元格样式
        HSSFCellStyle cellStyle = (HSSFCellStyle) wb.createCellStyle( );
        // 指定单元格居中对齐
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 指定单元格垂直居中对齐
        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        // 指定当单元格内容显示不下时自动换行
        cellStyle.setWrapText(true);
        // 设置单元格字体
        HSSFFont font = (HSSFFont) wb.createFont( );
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 12);
        cellStyle.setFont(font);
        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 下边框
        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);// 左边框
        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);// 上边框
        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);// 右边框
        return cellStyle;
    }


    /**
     * 获得标题的样式
     *
     * @param wb
     * @return
     */
    public static XSSFCellStyle getBodyXSSFCellStyle(Workbook wb) {
        // 创建单元格样式
        XSSFCellStyle cellStyle = (XSSFCellStyle) wb.createCellStyle( );
        // 指定单元格居中对齐
        cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
        // 指定单元格垂直居中对齐
        cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
        // 指定当单元格内容显示不下时自动换行
        cellStyle.setWrapText(true);
        // 设置单元格字体
        XSSFFont font = (XSSFFont) wb.createFont( );
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 12);
        cellStyle.setFont(font);
        cellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN); // 下边框
        cellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);// 左边框
        cellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);// 上边框
        cellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN);// 右边框
        return cellStyle;
    }
    //使用POI读入excel工作簿文件
    public static void readWorkBook() throws Exception {
        // poi读取excel
        //创建要读入的文件的输入流
        InputStream inp = new FileInputStream("workbook.xls");

        //根据上述创建的输入流 创建工作簿对象
        Workbook wb = WorkbookFactory.create(inp);
        //得到第一页 sheet
        //页Sheet是从0开始索引的
        Sheet sheet = wb.getSheetAt(0);
        //利用foreach循环 遍历sheet中的所有行
        for (Row row : sheet) {
            //遍历row中的所有方格
            for (Cell cell : row) {
                //输出方格中的内容，以空格间隔
                System.out.print(cell.toString( ) + "  ");
            }
            //每一个行输出之后换行
            System.out.println( );
        }
        //关闭输入流
        inp.close( );
    }
}
